home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
pcmagazi
/
1992
/
04
/
sort.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-05
|
4KB
|
163 lines
// sort.cpp RHS 7/29/91
#include "sort.h"
/*-----------------------------------------------------------------------*
Name Swap - exchanges two objects
Usage void near pascal Swap (void *left,
void *right);
Description exchanges the elWidth byte wide objects pointed to
by left and right.
Return value Nothing
*------------------------------------------------------------------------*/
void near pascal swap2(FARPPV left, FARPPV right)
{
asm push Ds
asm cld
// note that elWidth is never 0, since it's tested at entry to QSort
asm mov Cx, 4
asm les Di, right
asm lds Si, left
asm shr Cx, 1 // test for an odd number of bytes
asm jnc xch_wordLoop
asm mov Al, Es:[Di]
asm movsb // swap bytes, advancing pointers
asm mov [Si-1], Al
asm jz xch_end // if CX was originally 1
xch_wordLoop:
asm mov Ax, Es:[Di]
asm movsw // swap words, advancing pointers
asm mov [Si-2], Ax
asm loop xch_wordLoop
xch_end:
asm pop Ds
return;
}
void near pascal Sort::Swap(void FAR *left, void FAR *right)
{
int i;
unsigned char c;
for(i = 0; i < elWidth; i++)
{
c = *((unsigned char far *)right);
*((unsigned char *)right)++ = *((unsigned char far *)left);
*((unsigned char far *)left)++ = c;
}
return;
}
/*
Optimize pointer comparisons knowing segments are identical,
except in HUGE model.
*/
/*-----------------------------------------------------------------------*
Name QSort - performs the quicker sort
Usage void near pascal QSort (char *base,
size_t numEl);
Description performs the quicker sort on the numEl element array
pointed to by base.
Return value Nothing
*------------------------------------------------------------------------*/
#pragma warn -sig
void near pascal Sort::QSort(char FAR *base, size_t numEl)
{
char FAR *left, FAR *right;
unsigned lNum;
TailRecursionOpt:
if(numEl < 2)
{
if(numEl == 2)
if(PCmpFunc(base, right = elWidth + base) > 0)
swap2((FARPPV) base, (FARPPV) right);
return;
}
right = (numEl - 1) * elWidth + base;
left = (numEl >> 1) * elWidth + base;
// sort the pivot, left, and right elements for "median of 3"
if(PCmpFunc(left, right) > 0)
swap2((FARPPV) left, (FARPPV) right);
if(PCmpFunc(left, base) > 0)
swap2((FARPPV) left, (FARPPV) base);
else if(PCmpFunc(base, right) > 0)
swap2((FARPPV) base, (FARPPV) right);
if(numEl == 3)
{
swap2((FARPPV) base, (FARPPV) left);
return;
}
// now for the classic Hoare algorithm
left = elWidth + base;
do
{
while(PCmpFunc(left, base) < 0)
if(left < right)
left += elWidth;
else
goto Break;
while(left < right)
if(PCmpFunc(base, right) <= 0)
right -= elWidth;
else
{
swap2((FARPPV) left, (FARPPV) right);
left += elWidth;
right -= elWidth;
break;
}
}
while(left < right);
Break:
if(PCmpFunc(left, base) < 0)
swap2((FARPPV) left, (FARPPV) base);
lNum = (left - base) / elWidth;
if(numEl -= lNum)
QSort(left, numEl);
numEl = lNum;
goto TailRecursionOpt;
}
#pragma warn .sig
void Sort::QuickSort(void FAR *base, size_t numEl, size_t width, CmpFunc *compar)
{
if((elWidth = width) == 0)
return;
PCmpFunc = compar;
QSort((char FAR *)base, numEl);
}